package cn.hd01.weixin;

import cn.hd01.repository.entity.User;
import cn.hd01.repository.entity.Order;
import cn.hd01.repository.entity.WXApp;
import cn.hd01.repository.entity.WXOauth;
import cn.hd01.service.UserService;
import cn.hd01.service.OrderService;
import cn.hd01.service.WXAppService;
import cn.hd01.util.NetUtil;
import cn.hd01.web.auth.Auth;
import cn.hd01.web.auth.AuthType;
import cn.hd01.web.util.WebConstant;
import cn.hd01.web.util.WebException;
import cn.hd01.web.util.WebHelper;
import cn.hd01.weixin.model.PrePayData;
import cn.hd01.weixin.service.WeixinPayService;
import cn.hd01.weixin.util.WeiXinUtils;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
import java.util.SortedMap;

/**
 * 微信支付
 *
 * @author cyb
 * @date 2017/4/25.
 */
@Controller
@RequestMapping("/weixin/pay")
@Auth(AuthType.WECHAT)
public class WeiXinPayController {
    private static final Logger logger = LoggerFactory.getLogger(WeiXinPayController.class);

    @Value("${weixin.pay.rmb}")
    private double payRmb;

    @Autowired
    private WXAppService appService;

    @Autowired
    private WeixinPayService weixinPayService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;

    /**
     * 取消合作支付
     */
    @ResponseBody
    @RequestMapping(path = "/cancelRights")
    public void cancelRights(){
        WXOauth wxOauth = WebHelper.currentWXOauth();

        User mallUser = userService.findByOauthId(wxOauth.getId());
        if (mallUser != null) {
            userService.updateRightsPay(mallUser.getId(), 2);
        }
    }

    /**
     * 合作支付
     * 通过菜单 合作支付入口
     */
    @RequestMapping(path = "/rightsPay", method = RequestMethod.GET)
    public String rightsPay(Model model) {
        WXOauth wxOauth = WebHelper.currentWXOauth();

        User mallUser = userService.findByOauthId(wxOauth.getId());
        if (null == mallUser) {
            WebHelper.session().setAttribute(WebConstant.REDIRECT_URL, WebHelper.fullUrl());
            return "redirect:/weixin/mall/choseRegister";
        }

        // 非设计师或供应商
        if (mallUser.getType() != 1 && mallUser.getType() != 2) {
            return "weixin/noAccess";
        }

        if (mallUser.getRightsPay() == 2){
            model.addAttribute("hasChoose", true);
        } else{
            Order order = orderService.findByUserIdAndType(mallUser.getId(), 0);
            if (order == null) {
                order = orderService.save(Order.createOrder(mallUser, 0, (long)(payRmb * 100), mallUser.getId().toString()));
            }

            model.addAttribute("hasChoose", order.hasPay());
            model.addAttribute("orderId", order.getOrderId());
            model.addAttribute("money", payRmb);
        }

        if (mallUser.getType() == 1) {
            return "weixin/pay/rightsPay";
        } else if (mallUser.getType() == 2) {
            return "weixin/pay/supplierRightsPay";
        }

        return "weixin/noAccess";
    }

    /**
     * 微信下单
     *
     * @param o       存放orderId
     * @param request
     * @param session
     * @return
     */
    @RequestMapping(path = "/unifiedOrder")
    @ResponseBody
    public PrePayData unifiedOrder(Order o, HttpServletRequest request, HttpSession session) {
        WXApp app = appService.findByWeixinId(WebHelper.currentWXOauth().getWeixinId());

        WXOauth wxOauth = (WXOauth) session.getAttribute(WebConstant.USER_SESSION_NAME);
        String notifyUrl = WebHelper.basePath() + "/weixin/pay/payNotify";

        Order order = orderService.findOne(o.getOrderId());
        if (order == null) {
            return new PrePayData(0, "订单不存在");
        } else if (order.hasPay()) {
            return new PrePayData(0, "订单已支付");
        }

        //构建微信统一下单需要的参数
        Map<String, Object> map = Maps.newHashMap();
        map.put("openId", wxOauth.getOpenId());//用户标识openId
        map.put("remoteIp", NetUtil.getRemoteAddrIp(request));//请求Ip地址
        map.put("body", "权益保证费用"); // 商品描述
        map.put("tradeType", WeiXinUtils.TRADE_TYPE_JSAPI); // 公众号支付方式

        //调用统一下单service
        Map<String, Object> resultMap = weixinPayService.unifiedOrder(app, notifyUrl, order, map);

        String returnCode = (String) resultMap.get("return_code");//通信标识
        String resultCode = (String) resultMap.get("result_code");//交易标识
        //只有当returnCode与resultCode均返回“success”，才代表微信支付统一下单成功
        if (WeiXinUtils.RETURN_SUCCESS.equals(returnCode) && WeiXinUtils.RETURN_SUCCESS.equals(resultCode)) {
            String appId = (String) resultMap.get("appid");//微信公众号AppId
            String timeStamp = WeiXinUtils.getTimeStamp();//当前时间戳
            String prepayId = "prepay_id=" + resultMap.get("prepay_id");//统一下单返回的预支付id
            String nonceStr = WeiXinUtils.nonceStr();
            SortedMap<String, Object> signMap = Maps.newTreeMap();//自然升序map
            signMap.put("appId", appId);
            signMap.put("package", prepayId);
            signMap.put("timeStamp", timeStamp);
            signMap.put("nonceStr", nonceStr);
            signMap.put("signType", "MD5");

//            model.addAttribute("appId", appId);
//            model.addAttribute("timeStamp", timeStamp);
//            model.addAttribute("nonceStr", nonceStr);
//            model.addAttribute("prepayId", prepayId);
//            model.addAttribute("paySign", WeiXinUtils.getSign(signMap, app.getShKey()));//获取签名

            PrePayData prePayData = new PrePayData(1, "微信下单成功");
            prePayData.setAppId(appId);
            prePayData.setTimeStamp(timeStamp);
            prePayData.setNonceStr(nonceStr);
            prePayData.setPrepayId(prepayId);
            prePayData.setPaySign(WeiXinUtils.getSign(signMap, app.getShKey()));//获取签名

            //将支付需要参数返回至页面，采用h5方式调用支付接口
            return prePayData;
        } else {
            logger.error("微信统一下单失败,订单编号:" + order.getOrderId() + ",失败原因:" + resultMap.get("err_code_des") + ", 描述:" + resultMap.get("return_msg"));
            return new PrePayData(0, "微信下单失败");//支付下单失败，重定向至订单列表
        }
    }

    /**
     * 提交支付后的微信异步返回接口
     */
    @RequestMapping(value = "/payNotify")
    @Auth(AuthType.OFF)
    public void payNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            Map<String, Object> resultMap = WeiXinUtils.parseXml(request.getInputStream());
            String orderId = (String) resultMap.get("out_trade_no");
            String return_code = (String) resultMap.get("return_code");
            String sign = (String) resultMap.get("sign");
            String mch_id = (String) resultMap.get("mch_id");

            WXApp app = appService.findByMchId(mch_id);
            if (app == null) {
                response.getWriter().write(WeiXinUtils.payNotifyReturn("FAIL", "商户不存在"));
                return;
            }

            String expectSign = WeiXinUtils.getSign(resultMap, app.getShKey());
            if (!sign.equals(expectSign)) {
                response.getWriter().write(WeiXinUtils.payNotifyReturn("FAIL", "签名校验失败"));
                return;
            }

            if (return_code.equals("SUCCESS")) {
                orderService.updateStatusByOrderId(1, orderId);

                Order order = orderService.findByOrderId(orderId);
                userService.updateRightsPay(order.getUserId(), 1);
            } else {
                //支付失败的业务逻辑，先记录日志吧
                logger.error("订单支付失败:{}", orderId);
            }

            //通知微信.异步确认成功
            response.getWriter().write(WeiXinUtils.payNotifyReturn("SUCCESS", ""));
        } catch (Exception e) {
            logger.error("微信回调接口出现错误：", e);
            try {
                response.getWriter().write(WeiXinUtils.payNotifyReturn("FAIL", "error"));
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

}
